package model

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"encoding/base64"
	"errors"
	"io"
)

// JenkinsCredential Jenkins凭据模型
type JenkinsCredential struct {
	BaseModel
	Deleted              bool   `json:"deleted" gorm:"type:tinyint(1);default:0;uniqueIndex:idx_credential_id_deleted;column:deleted;comment:是否删除"`
	CredentialId         string `json:"credentialId" gorm:"type:varchar(255);not null;uniqueIndex:idx_credential_id_deleted;column:credential_id;comment:凭据ID"`
	Description          string `json:"description" gorm:"type:text;column:description;comment:描述"`
	Type                 string `json:"type" gorm:"type:varchar(50);not null;column:type;comment:凭据类型"`
	Username             string `json:"username" gorm:"type:varchar(255);column:username;comment:用户名"`
	PasswordEncrypted    string `json:"-" gorm:"type:text;column:password_encrypted;comment:加密后的密码"`
	PrivateKeyEncrypted  string `json:"-" gorm:"type:text;column:private_key_encrypted;comment:加密后的私钥"`
	PassphraseEncrypted  string `json:"-" gorm:"type:text;column:passphrase_encrypted;comment:加密后的密码短语"`
	SecretTextEncrypted  string `json:"-" gorm:"type:text;column:secret_text_encrypted;comment:加密后的密钥文本"`
	CertificateEncrypted string `json:"-" gorm:"type:text;column:certificate_encrypted;comment:加密后的证书"`
	Scope                string `json:"scope" gorm:"type:varchar(20);default:'GLOBAL';column:scope;comment:作用域"`
	JenkinsServerId      uint64 `json:"jenkinsServerId" gorm:"type:bigint(20) unsigned;column:jenkins_server_id;comment:Jenkins服务器ID"`
	UsageCount           int    `json:"usageCount" gorm:"type:int;default:0;column:usage_count;comment:使用次数"`
}

// TableName 指定表名
func (JenkinsCredential) TableName() string {
	return "jenkins_credentials"
}

// 凭据类型常量
const (
	CredentialTypeUsernamePassword = "usernamePassword"
	CredentialTypeSSHKey           = "sshKey"
	CredentialTypeSecretText       = "secretText"
	CredentialTypeCertificate      = "certificate"
)

// 作用域常量
const (
	CredentialScopeGlobal = "GLOBAL"
	CredentialScopeSystem = "SYSTEM"
)

// EncryptData 加密数据
func EncryptData(plaintext string) (string, error) {
	if plaintext == "" {
		return "", nil
	}

	// 使用配置中的密钥
	key := []byte(C.General.SecretKey)
	if len(key) < 32 {
		// 如果密钥长度不足32位，用0填充
		padding := make([]byte, 32-len(key))
		key = append(key, padding...)
	} else if len(key) > 32 {
		// 如果密钥长度超过32位，截取前32位
		key = key[:32]
	}

	block, err := aes.NewCipher(key)
	if err != nil {
		return "", err
	}

	gcm, err := cipher.NewGCM(block)
	if err != nil {
		return "", err
	}

	nonce := make([]byte, gcm.NonceSize())
	if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
		return "", err
	}

	ciphertext := gcm.Seal(nonce, nonce, []byte(plaintext), nil)
	return base64.StdEncoding.EncodeToString(ciphertext), nil
}

// DecryptData 解密数据
func DecryptData(ciphertext string) (string, error) {
	if ciphertext == "" {
		return "", nil
	}

	// 使用配置中的密钥
	key := []byte(C.General.SecretKey)
	if len(key) < 32 {
		// 如果密钥长度不足32位，用0填充
		padding := make([]byte, 32-len(key))
		key = append(key, padding...)
	} else if len(key) > 32 {
		// 如果密钥长度超过32位，截取前32位
		key = key[:32]
	}

	data, err := base64.StdEncoding.DecodeString(ciphertext)
	if err != nil {
		return "", err
	}

	block, err := aes.NewCipher(key)
	if err != nil {
		return "", err
	}

	gcm, err := cipher.NewGCM(block)
	if err != nil {
		return "", err
	}

	nonceSize := gcm.NonceSize()
	if len(data) < nonceSize {
		return "", errors.New("ciphertext too short")
	}

	nonce, cipherData := data[:nonceSize], data[nonceSize:]
	plaintext, err := gcm.Open(nil, nonce, cipherData, nil)
	if err != nil {
		return "", err
	}

	return string(plaintext), nil
}

// SetPassword 设置密码（加密存储）
func (jc *JenkinsCredential) SetPassword(password string) error {
	encrypted, err := EncryptData(password)
	if err != nil {
		return err
	}
	jc.PasswordEncrypted = encrypted
	return nil
}

// GetPassword 获取密码（解密）
func (jc *JenkinsCredential) GetPassword() (string, error) {
	return DecryptData(jc.PasswordEncrypted)
}

// SetPrivateKey 设置私钥（加密存储）
func (jc *JenkinsCredential) SetPrivateKey(privateKey string) error {
	encrypted, err := EncryptData(privateKey)
	if err != nil {
		return err
	}
	jc.PrivateKeyEncrypted = encrypted
	return nil
}

// GetPrivateKey 获取私钥（解密）
func (jc *JenkinsCredential) GetPrivateKey() (string, error) {
	return DecryptData(jc.PrivateKeyEncrypted)
}

// SetPassphrase 设置密码短语（加密存储）
func (jc *JenkinsCredential) SetPassphrase(passphrase string) error {
	encrypted, err := EncryptData(passphrase)
	if err != nil {
		return err
	}
	jc.PassphraseEncrypted = encrypted
	return nil
}

// GetPassphrase 获取密码短语（解密）
func (jc *JenkinsCredential) GetPassphrase() (string, error) {
	return DecryptData(jc.PassphraseEncrypted)
}

// SetSecretText 设置密钥文本（加密存储）
func (jc *JenkinsCredential) SetSecretText(secretText string) error {
	encrypted, err := EncryptData(secretText)
	if err != nil {
		return err
	}
	jc.SecretTextEncrypted = encrypted
	return nil
}

// GetSecretText 获取密钥文本（解密）
func (jc *JenkinsCredential) GetSecretText() (string, error) {
	return DecryptData(jc.SecretTextEncrypted)
}

// SetCertificate 设置证书（加密存储）
func (jc *JenkinsCredential) SetCertificate(certificate string) error {
	encrypted, err := EncryptData(certificate)
	if err != nil {
		return err
	}
	jc.CertificateEncrypted = encrypted
	return nil
}

// GetCertificate 获取证书（解密）
func (jc *JenkinsCredential) GetCertificate() (string, error) {
	return DecryptData(jc.CertificateEncrypted)
}
